package com.atguigu.tingshu.user.service.impl;
import java.util.*;
import java.util.stream.Collectors;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.anno.GuiguCache;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.user.context.UpdateUserPaidRecordStrategyContext;
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
import com.atguigu.tingshu.user.mapper.UserPaidAlbumMapper;
import com.atguigu.tingshu.user.mapper.UserPaidTrackMapper;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.strategy.UpdateUserPaidRecordStrategy;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private WxMaService wxMaService ;

	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper ;

	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper ;

	@Autowired
	private RedisTemplate<String , String> redisTemplate ;

	@Autowired
	private KafkaService kafkaService ;

	@Override
	public String wxLogin(String code) {
		log.info("UserInfoServiceImpl...wxLogin...code:{}", code) ;

		try{
			//发送请求,校验凭证
			WxMaJscode2SessionResult sessionResult = wxMaService.getUserService().getSessionInfo(code);

			String openId = sessionResult.getOpenid();

			//根据openId查询数据
			LambdaQueryWrapper<UserInfo> userInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
			userInfoLambdaQueryWrapper.eq(UserInfo::getWxOpenId,openId);
			UserInfo userInfo = userInfoMapper.selectOne(userInfoLambdaQueryWrapper);

			if (userInfo==null){
				 userInfo = new UserInfo();
				 userInfo.setWxOpenId(openId);
				 userInfo.setNickname("五条悟");
				 userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
				 userInfoMapper.insert(userInfo);
				// 初始化新注册的用户的账号信息
				kafkaService.sendMessage(KafkaConstant.QUEUE_USER_REGISTER,userInfo.getId().toString());

			}

			//保存用户的登录状态
			String token = UUID.randomUUID().toString().replace("-","");

			// 把用户信息存储到Redis中
			userInfo.setPassword(null);

			//用户信息保存到redis当中
			redisTemplate.opsForValue().set(RedisConstant.RANKING_KEY_PREFIX+token,JSON.toJSONString(userInfo));

			//返回token
			return token;


		}catch (Exception e) {
			e.printStackTrace();
			throw new GuiguException(ResultCodeEnum.LOGIN_ERROR) ;

		}

	}

	@Override
	public UserInfoVo getUserInfo() {
		//获取当前用户的id
		Long userId = AuthContextHolder.getUserId();

	    //根据id查询用户信息
		UserInfo userInfo = userInfoMapper.selectById(userId);

		//再把用户数据转换为UserInfoVo
		UserInfoVo userInfoVo = new UserInfoVo();
		userInfoVo.setId(userInfo.getId());
		userInfoVo.setWxOpenId(userInfo.getWxOpenId());
		userInfoVo.setNickname(userInfo.getNickname());
		userInfoVo.setAvatarUrl(userInfo.getAvatarUrl());
		userInfoVo.setIsVip(userInfo.getIsVip());
		userInfoVo.setVipExpireTime(userInfo.getVipExpireTime());


        return userInfoVo;
	}

	@Override
	public void updateUser(UserInfoVo userInfoVo) {
		//查询用户id
		Long userId = AuthContextHolder.getUserId();

		//根据id查询用户数据
		UserInfo userInfo  = userInfoMapper.selectById(userId);
		userInfo.setNickname(userInfoVo.getNickname());
		userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());

		userInfoMapper.updateById(userInfo);
	}

	@GuiguCache(cacheKey = "user:info:" + "#{#params[0]}")
	@Override
	public UserInfoVo findUserInfoVoByUserId(Long userId) {
		UserInfo userInfo = this.getById(userId);
		UserInfoVo userInfoVo = new UserInfoVo() ;
		BeanUtils.copyProperties(userInfo , userInfoVo);
		return userInfoVo;
	}

	@Override
	public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIds) {
		// 创建Map对象，用来存储结果数据
		Map<Long  , Integer> result = new HashMap<>() ;

		// 获取当前登录用户的id
		Long userId = AuthContextHolder.getUserId();

		// 判断用户是否购买过专辑
		LambdaQueryWrapper<UserPaidAlbum> lambdaQueryWrapper = new LambdaQueryWrapper<>() ;
		lambdaQueryWrapper.eq(UserPaidAlbum::getUserId, userId) ;
		lambdaQueryWrapper.eq(UserPaidAlbum::getAlbumId , albumId) ;
		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(lambdaQueryWrapper);
		if(userPaidAlbum != null) {		// 购买过这个专辑
			trackIds.stream().forEach(trackId -> result.put(trackId , 1));
		}else {		// 查询用户针对该专辑所购买过的声音

			LambdaQueryWrapper<UserPaidTrack> userPaidTrackLambdaQueryWrapper = new LambdaQueryWrapper<>() ;
			userPaidTrackLambdaQueryWrapper.eq(UserPaidTrack::getUserId, userId) ;
			userPaidTrackLambdaQueryWrapper.eq(UserPaidTrack::getAlbumId ,albumId) ;
			List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(userPaidTrackLambdaQueryWrapper);
			if(CollectionUtils.isEmpty(userPaidTracks)) {   // 没有购买过
				trackIds.stream().forEach(trackId -> result.put(trackId , 0));
			}else {
				List<Long> paidTrackIds = userPaidTracks.stream().map(userPaidTrack -> userPaidTrack.getTrackId()).collect(Collectors.toList());
				trackIds.stream().forEach(trackId -> {
					if(paidTrackIds.contains(trackId)) {		// 购买过当前声音
						result.put(trackId , 1) ;
					}else {
						result.put(trackId , 0) ;				// 未购买过声音
					}
				});
			}

		}
		return  result;
	}


	@Override
	public List<Long> findUserPaidTrackList(Long albumId) { //查询当前用户购买的全部声音

		// 根据当前登录的用户的id以及专辑的id查询用户购买的声音的列表
		Long userId = AuthContextHolder.getUserId();

		LambdaQueryWrapper<UserPaidTrack> lambdaQueryWrapper = new LambdaQueryWrapper<>() ;
		lambdaQueryWrapper.eq(UserPaidTrack::getUserId, userId) ;
		lambdaQueryWrapper.eq(UserPaidTrack::getAlbumId , albumId) ;
		lambdaQueryWrapper.select(UserPaidTrack::getTrackId) ;			// 指定查询的列数据

		List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(lambdaQueryWrapper);
		List<Long> collected = userPaidTrackList.stream().map(userPaidTrack -> userPaidTrack.getTrackId()).collect(Collectors.toList());

		return collected;
	}

	@Override
	public void updateUserPaidRecord(UserPaidRecordVo userPaidRecordVo) {

		// 根据付款项目的类型保存交易信息【策略设计模式进行改造】
		String itemType = userPaidRecordVo.getItemType();
		UpdateUserPaidRecordStrategy updateUserPaidRecordStrategy = UpdateUserPaidRecordStrategyContext.getUpdateUserPaidRecordStrategy(itemType);
		updateUserPaidRecordStrategy.updateUserPaidRecord(userPaidRecordVo) ;

	}


}

